Cleanup backend block device logic under save/restore; this should
authorsmh22@firebug.cl.cam.ac.uk <smh22@firebug.cl.cam.ac.uk>
Tue, 29 Nov 2005 13:50:30 +0000 (14:50 +0100)
committersmh22@firebug.cl.cam.ac.uk <smh22@firebug.cl.cam.ac.uk>
Tue, 29 Nov 2005 13:50:30 +0000 (14:50 +0100)
fix the issues some people have seen with segfaults in vbd_translate
and/or user-space hangs.

Signed-off-by: Steven Hand <steven@xensource.com>
linux-2.6-xen-sparse/drivers/xen/blkback/common.h
linux-2.6-xen-sparse/drivers/xen/blkback/interface.c
linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c

index bd22c4033234eda44f48ff7142d0f68a65a65075..96eafda2fec94ea382f64f8a66ebc9791771d235 100644 (file)
@@ -38,6 +38,8 @@ struct vbd {
        struct block_device *bdev;
 }; 
 
+struct backend_info; 
+
 typedef struct blkif_st {
        /* Unique identifier for this interface. */
        domid_t           domid;
@@ -48,8 +50,10 @@ typedef struct blkif_st {
        /* Comms information. */
        blkif_back_ring_t blk_ring;
        struct vm_struct *blk_ring_area;
-       /* VBDs attached to this interface. */
+       /* The VBD attached to this interface. */
        struct vbd        vbd;
+       /* Back pointer to the backend_info. */
+       struct backend_info *be; 
        /* Private fields. */
        enum { DISCONNECTED, CONNECTED } status;
 #ifdef CONFIG_XEN_BLKDEV_TAP_BE
@@ -103,6 +107,8 @@ void blkif_xenbus_init(void);
 
 irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);
 
+void update_blkif_status(blkif_t *blkif); 
+
 #endif /* __BLKIF__BACKEND__COMMON_H__ */
 
 /*
index fd8eccec8de6be6946f74043b48680d3f6ef0913..900b48271958f3e8aabd69d44259e8a1e68ae00a 100644 (file)
@@ -112,7 +112,9 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
 
        blkif->irq = bind_evtchn_to_irqhandler(
                blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif);
-       blkif->status = CONNECTED;
+
+       /* We're potentially connected now */
+       update_blkif_status(blkif); 
 
        return 0;
 }
index b119efa697a6ed4fb43db491c0479fc9c13b8258..a5a3113e44a7c490f47ba7671aa9e32e71837a53 100644 (file)
@@ -50,6 +50,16 @@ static void backend_changed(struct xenbus_watch *, const char **,
                            unsigned int);
 
 
+void update_blkif_status(blkif_t *blkif)
+{ 
+       if(blkif->irq && blkif->vbd.bdev) {
+               blkif->status = CONNECTED; 
+               (void)blkif_be_int(0, blkif, NULL); 
+       }
+       maybe_connect(blkif->be); 
+}
+
+
 static ssize_t show_physical_device(struct device *_dev, char *buf)
 {
        struct xenbus_device *dev = to_xenbus_device(_dev);
@@ -81,6 +91,7 @@ static int blkback_remove(struct xenbus_device *dev)
                be->backend_watch.node = NULL;
        }
        if (be->blkif) {
+               be->blkif->status = DISCONNECTED; 
                blkif_put(be->blkif);
                be->blkif = NULL;
        }
@@ -123,6 +134,9 @@ static int blkback_probe(struct xenbus_device *dev,
                goto fail;
        }
 
+       /* setup back pointer */
+       be->blkif->be = be; 
+
        err = xenbus_watch_path2(dev, dev->nodename, "physical-device",
                                 &be->backend_watch, backend_changed);
        if (err)
@@ -209,7 +223,8 @@ static void backend_changed(struct xenbus_watch *watch,
                device_create_file(&dev->dev, &dev_attr_physical_device);
                device_create_file(&dev->dev, &dev_attr_mode);
 
-               maybe_connect(be);
+               /* We're potentially connected now */
+               update_blkif_status(be->blkif); 
        }
 }
 
@@ -235,7 +250,7 @@ static void frontend_changed(struct xenbus_device *dev,
                if (err) {
                        return;
                }
-               maybe_connect(be);
+               update_blkif_status(be->blkif); 
                break;
 
        case XenbusStateClosing: